package com.ngmaster.socket;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.Arrays;
import java.util.List;

/**
 * 消息的粘包与分包处理
 */
public class MessageFrameDecoder extends ByteToMessageDecoder {

	/**
	 * 最大的消息长度
	 */
	private int maxMessageLength = 0;

	/**
	 * 消息最小长度
	 */
	private final int MESSAGE_LAST_LENGTH = 16;

	private final int IC_CID_LENGTH = 10;

	private final int CMD_LENGTH = 1;

	private final int DATA_CONTENT_LENGTH = 2;

	public static final int CRC_LENGTH = 2;
	
	/**
	 * 最大的消息长度
	 * @param maxMessageLength
	 */
	public MessageFrameDecoder(int maxMessageLength) {
		this.maxMessageLength = maxMessageLength;
	}
	
	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {

		while(canDecode(ctx, in))
			decodeMessage(ctx, in, out);


	}

	private void decodeMessage(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
		int readableByteLength = in.readableBytes();
		in.markReaderIndex();
		byte[] icCidBytes = new byte[IC_CID_LENGTH];
		in.readBytes(icCidBytes); // 读出来iccid
		byte cmd = in.readByte(); /// 读出来cmd
		short dataLength = in.readShort(); // 读出来可变消息体的长度
		int messageLength = IC_CID_LENGTH + CMD_LENGTH + DATA_CONTENT_LENGTH + dataLength + CRC_LENGTH;

		byte[] messageBytes = new byte[messageLength];
		in.resetReaderIndex();
		in.readBytes(messageBytes);
		if (NetManager.getInstance().getLogger().isInfoEnabled()) {
			NetManager.getInstance().getLogger().info("[remoteAddress:{}] [收到数据总长度:{}] [收到:{}] [16进制:{}]",
					new Object[]{
							ctx.channel().remoteAddress(),
							readableByteLength,
							Arrays.toString(messageBytes),
							BitConverter.bytesToHexString(messageBytes)
					});
		}
		in.resetReaderIndex();
		ByteBuf message = ctx.alloc().buffer(messageLength);
		in.readBytes(message);
		out.add(message);
	}
	
	/**
	 * 是否可以解析
	 * @return
	 */
	protected boolean canDecode(ChannelHandlerContext ctx, ByteBuf in) {
		int readableLength = in.readableBytes();
		if (readableLength < MESSAGE_LAST_LENGTH) {
			return false;
		}
		
		in.markReaderIndex();
		byte[] icCidBytes = new byte[IC_CID_LENGTH];
		in.readBytes(icCidBytes); // 读出来iccid
		byte cmd = in.readByte(); /// 读出来cmd
		short dataLength = in.readShort(); // 读出来可变消息体的长度
		int messageLength = IC_CID_LENGTH + CMD_LENGTH + DATA_CONTENT_LENGTH + dataLength + CRC_LENGTH;
		if (readableLength < messageLength) {
			in.resetReaderIndex();
			return false;
		}
		
		in.resetReaderIndex();
		return true;
	}

//	protected boolean canDecode(ChannelHandlerContext ctx, ByteBuf in) {
//		if( in.readableBytes() < Message_Head_Length )
//			return false;
//
//		in.markReaderIndex();
//		byte[] byteLength = new byte[Message_Head_Length];
//		in.readBytes(byteLength);
//		int dataLength = BitConverter.toInt(byteLength, 0);
//		if( dataLength <= 0 || dataLength > maxMessageLength)
//		{
//			in.resetReaderIndex();
//			ctx.close();
//			return false;
//		}
//
//		if( in.readableBytes() < dataLength )
//		{
//			in.resetReaderIndex();
//			return false;
//		}
//
//		in.resetReaderIndex();
//		return true;
//	}
	
	/**
	 * 解析一个消息
	 */
//	protected void decodeMessage(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
//		in.markReaderIndex();
//		byte[] byteLength = new byte[Message_Head_Length];
//		in.readBytes(byteLength);
//		int dataLength = BitConverter.toInt(byteLength, 0);
//
//		int messageLength = dataLength + Message_Head_Length;
//		in.resetReaderIndex();
//
//		ByteBuf message = ctx.alloc().buffer(messageLength);
//		in.readBytes(message);
//		out.add(message);
//	}
}
